package com.lin.sys.service.impls;

import com.auth0.jwt.JWT;
import com.google.gson.Gson;
import com.lin.config.RedisUtils;
import common.oauth2.TokenUtil;

import dto.*;
import org.apache.dubbo.config.annotation.Service;

import com.lin.common.service.impl.BaseService;


import com.lin.sys.dao.SysUserMapper;
import com.lin.sys.dao.SysUserRoleMapper;
import com.lin.sys.entity.SysUser;
import com.lin.sys.entity.SysUserRole;
import com.lin.sys.entity.UserWithRole;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import service.MenuService;
import service.RoleService;
import service.UserRoleService;
import service.UserService;
import tk.mybatis.mapper.entity.Example;
import util.BeanUtils;
import util.MD5Util;
import util.ResponseVo;

import java.util.*;

@Slf4j
@Service
public class UserServiceImpl extends BaseService<SysUser> implements UserService {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Value("${tokenExpire}")
    Long tokenExpire;

//    @Autowired
//    StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    @Lazy
    private UserService userService;
    @Autowired
    @Lazy
    private RoleService roleService;
    @Autowired
    @Lazy
    private MenuService menuService;
    @Override
    public ResponseVo login(String username, String password) {

        password = MD5Util.encrypt(username.toLowerCase(), password);

        SysUserDto sysUser = findByName(username);

        if(null == sysUser){
            return ResponseVo.error("用户名不存在");
        }
        if(!sysUser.getPassword().equals(password)){
            return ResponseVo.error("密码错误");
        }
        if(sysUser.getStatus().equals(0)){
            return ResponseVo.error("账号已锁定");
        }
        log.info("userid: {}",sysUser.getUserId());
        //缓存token
        String token = TokenUtil.sign(sysUser.getUserId(), sysUser.getPassword());
    //    stringRedisTemplate.opsForValue().set(token+"cache",sysUser.getUserId()+"",2*tokenExpire, TimeUnit.SECONDS);
       // HashMap redis=new HashMap();
        RedisDto  redis=new RedisDto();
        // 获取用户角色集

        List<SysRoleDto> roleList = this.roleService.findUserRole(sysUser.getUserId());
        // 获取用户权限集
        List<SysMenuDto> permissionList = this.menuService.findUserPermissions(sysUser.getUserId());
        redis.setRoleList(roleList);
        redis.setPermissionList(permissionList);
        redis.setUserDto(sysUser);
      //  redisUtils.set(token+"cache",sysUser.getUserId()+"",2*tokenExpire);
      //  redisUtils.set(token+"cache",new Gson().toJson(redis),2*tokenExpire);
        redisUtils.set(sysUser.getUserId()+"cache",new Gson().toJson(redis),2*tokenExpire);
        Map<String,Object> data = new HashMap<>();
        data.put("token",token);
        data.put("username",sysUser.getUsername());
        return ResponseVo.ok("登陆成功",data);
    }

    @Override
    public ResponseVo refreshToken(String token) {
        Long usernId = TokenUtil.getUsernId(token);
        if (usernId!=null&&redisUtils.hasKey(usernId + "cache")) {
          //  Long id = Long.parseLong((String) redisUtils.get(token + "cache"));
            String cache = (String) redisUtils.get(usernId + "cache");
            RedisDto redisDto=new RedisDto();
            redisDto=new Gson().fromJson(cache,RedisDto.class);
            SysUserDto user=redisDto.getUserDto();
            if(user!=null){
                String newToken = TokenUtil.sign(user.getUserId(), user.getPassword());
                RedisDto  redis=new RedisDto();
                // 获取用户角色集
                List<SysRoleDto> roleList = this.roleService.findUserRole(user.getUserId());
                // 获取用户权限集
                List<SysMenuDto> permissionList = this.menuService.findUserPermissions(user.getUserId());
                redis.setRoleList(roleList);
                redis.setPermissionList(permissionList);
                redis.setUserDto(user);
                redisUtils.del(token+"cache");
              //  redisUtils.set(token+"cache",new Gson().toJson(redis),2*tokenExpire);
                redisUtils.set(user.getUserId()+"cache",new Gson().toJson(redis),2*tokenExpire);
                return ResponseVo.ok("refresh success",newToken);
            }
        }

        return ResponseVo.error("过期太久...");
    }

    @Override
    public SysUserDto findByName(String userName) {
        Example example = new Example(SysUser.class);
        example.createCriteria().andCondition("lower(username)=", userName.toLowerCase());
        List<SysUser> list = this.selectByExample(example);
        SysUserDto sysUserDto=new SysUserDto();
        if (list.size()==0) {
            sysUserDto=null;
        }else {
            BeanUtils.copyProperties(list.get(0),sysUserDto);
        }
        return sysUserDto ;
    }

    @Override
    public List<SysUserDto> findUserMsg(SysUserDto user) {
        SysUser sysUser=new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        List<SysUser> userMsg = sysUserMapper.findUserMsg(sysUser);
        return BeanUtils.copyList(userMsg,SysUserDto.class);
    }

    @Override
    public void addUser(SysUserDto user, Long[] roles) {
        SysUser sysUser=new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        sysUser.setCrateTime(new Date());
        sysUser.setModifyTime(new Date());
        sysUser.setPassword(MD5Util.encrypt(user.getUsername(),user.getPassword()));
        log.info("user is:"+user.toString());
        this.save(sysUser);
        saveOrUpdateRole(sysUser, roles);

    }

    @Override
    public UserWithRoleDto findUserWithRole(SysUserDto user) {
        SysUser sysUser=new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        List<UserWithRole> userWithRole = sysUserMapper.findUserWithRole(sysUser);
        List<Long> roleList = new ArrayList<>();
        for (UserWithRole uwr : userWithRole) {
            roleList.add(uwr.getRoleId());
        }
        if (userWithRole.size() == 0) {
            return null;
        }
        UserWithRole uwr = userWithRole.get(0);
        uwr.setRoles(roleList);
        UserWithRoleDto userWithRoleDto=new UserWithRoleDto();
        BeanUtils.copyProperties(uwr,userWithRoleDto);
        return userWithRoleDto;
    }

    @Override
    public void updateUser(SysUserDto user, Long[] roles) {
        SysUser sysUser=new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        sysUser.setPassword(null);
        sysUser.setUsername(null);
        sysUser.setModifyTime(new Date());
        this.updateNotNull(sysUser);
        Example example = new Example(SysUserRole.class);
        example.createCriteria().andCondition("user_id=", user.getUserId());
        this.userRoleMapper.deleteByExample(example);
        saveOrUpdateRole(sysUser, roles);
    }

    @Override
    public void deleteUser(SysUserDto user) {
        this.delete(user.getUserId());
        userRoleService.deleteByUserId(user.getUserId());
    }

    @Override
    public SysUserDto select(Object key) {
        SysUserDto sysUserDto=new SysUserDto();
        SysUser sysUser = this.selectByKey(key);
        BeanUtils.copyProperties(sysUser,sysUserDto);
        return sysUserDto;
    }

    private void saveOrUpdateRole(SysUser user,Long[] roles){
        Arrays.stream(roles).forEach(role->{
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(role);
            this.userRoleMapper.insert(userRole);

        });

    }
}
